﻿namespace NoIdeaIoc;
internal class ServiceContainer
{
    readonly List<IResolveUnit> resolveUnits;
    readonly string serviceKey;
    public ServiceContainer(string serviceKey)
    {
        this.serviceKey = serviceKey;
        resolveUnits = new List<IResolveUnit>(3);
    }
    public IocResponse? ResolveInstance(LifeTime lifeTime, string keyName)
    {
        foreach (var tempUnit in resolveUnits.Where(x => x.EqualKeyName(keyName)))
        {
            var instance = tempUnit.ResolveInstance(lifeTime, keyName);
            if (instance == null) continue;
            var cacheKey = ResolveUnitBase.GetCacheKey(serviceKey, keyName);
            return new IocResponse(cacheKey, instance, tempUnit.ServiceLifetime);
        }
        return null;
    }
    public IEnumerable<IocResponse> ResolveInstanceEnumerable(LifeTime lifeTime, string keyName)
    {
        var cacheKey = ResolveUnitBase.GetCacheKey(serviceKey, keyName);
        foreach (var tempUnit in resolveUnits.Where(x => x.EqualKeyName(keyName)))
        {
            var instance = tempUnit.ResolveInstance(lifeTime, keyName);
            if (instance == null) continue;
            yield return new IocResponse(cacheKey, instance, tempUnit.ServiceLifetime);
        }
    }
    public IocResponse? ResolveInstance(LifeTime lifeTime, Type[] genericArgumentTypes, string keyName)
    {
        foreach (var tempUnit in resolveUnits.Where(x => x.EqualKeyName(keyName)))
        {
            var instance = tempUnit.ResolveInstance(lifeTime, genericArgumentTypes, keyName);
            if (instance == null) continue;
            return instance;
        }
        return null;
    }
    public void AddService(Func<IServiceProvider, object?, object> func, string keyName, ServiceLifetime serviceLifetime)
    {
        resolveUnits.Add(new ResolveUnitByKeyedFunc(func, keyName, serviceLifetime));
    }
    public void AddService(Func<IServiceProvider, object> func, ServiceLifetime serviceLifetime)
    {
        resolveUnits.Add(new ResolveUnitByFunc(func, null, serviceLifetime));
    }
    public void AddServiceFun(Func<LifeTime, string?, object> func, string keyName, ServiceLifetime serviceLifetime)
    {
        resolveUnits.Add(new ResolveUnitByServiceType(func, keyName, serviceLifetime));
    }
    public void AddServiceGenericTypeDefinition(Type serviceType, Type genericTypeDefinitionType, string keyName, ServiceLifetime serviceLifetime)
    {
        resolveUnits.Add(new ResolveUnitByGenericTypeDefinition(serviceType, genericTypeDefinitionType, keyName, serviceLifetime));
    }
    public void AddServiceGenericTypeDefinition(Type serviceType, Type genericTypeDefinitionType, ServiceLifetime serviceLifetime)
    {
        resolveUnits.Add(new ResolveUnitByGenericTypeDefinition(serviceType, genericTypeDefinitionType, null, serviceLifetime));
    }
    public void AddServiceEnumerableDefinition()
    {
        resolveUnits.Add(new ResolveUnitByEnumerableTypeDefinition(ServiceLifetime.Scoped));
    }
    /// <summary>
    /// 服务名
    /// </summary>
    public string ServiceKey => serviceKey;
    /// <summary>
    /// 判断是否服务键一致
    /// </summary>
    /// <param name="serviceKey"></param>
    /// <returns></returns>
    public bool EqualServiceKey(string serviceKey)
    {
        return this.serviceKey == serviceKey;
    }
}
